"""author: wenyao
   data: 2021/12/3
   project: cjh
"""

#推导式
#1、列表推导式
# a = [1,2,3,4,5,6,7]
# b = [x**2 for x in a if x % 2 == 1]
# print(b)
#
# b = []
# for x in a:
#     if x % 2 == 1:
#         b.append(x**2)
#
# #打印30以内能被3整除的数
# print([x for x in range(1,31) if not x % 3 ])
#
# #找到包含两个e的名字
# names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
#          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva', 'Elven']]
# for lst in names:
#     for name in lst:
#         if name.count("e") == 2:
#             print(name)
#
# print([name for lst in names for name in lst if name.count("e")==2])
#
# #过滤50以内能被3整除的数，如果这个数是奇数就返回0，如果是偶数就返回这个数本身
# print([x if x % 2 == 0 else 0 for x in range(1,51) if x % 3 == 0])
#
# #字典推导式
# d1 = {"a":1, "b":2}
# d2 = {v:k for k,v in d1.items()}
# print(d2)

#集合推导式,和列表推导式一致，只是这里使用{}
#自带去重功能
# lst = [-1,1,2,1]
# s1 = {i*i for i in lst}
# print(s1)

#
# q1 = ['a', 'ab', 'abc', 'abcd']
# q2 = [x.upper() for x in q1 if len(x) >= 3]
# print(q2)
#
# q3 = [(i, j) for i in range(0, 6) for j in range(0, 6) if i % 2 == 0 and j % 2 == 1]
# print(q3)

# d1 = {"a": 1, "b": 2}
# d2 = {v: k for k, v in d1.items()}  # 键值对换
# print(d2)

# q4 = {"B": 3, "b": 1, "a": 4, "A": 2}
# q5 = {k.lower(): q4.get(k.lower(), 0)+q4.get(k.upper(), 0) for k, v in q4.items()}
# print(q5)

#可迭代对象
#实现了__iter__方法，并且该方法返回一个迭代器的对象
# lst = ["x","y",1,2,3]
# print(dir(lst))
# lst_iter = lst.__iter__()
# print(lst_iter.__next__())
# print(next(lst_iter))

#
# from collections.abc import Iterable
# print(isinstance(lst, Iterable))
# print(isinstance(lst, list))
# print(isinstance(lst, str))

#可迭代对象
#容器类型  --  str， list， tuple， dict， set
#打开的文件files， socket等等

#迭代器
#实现__iter__和__next__方法的都叫做迭代器
#__iter__方法返回自身
#__next__不断返回下一个值
# str1 = "abc"
# result = str1.__iter__()
# print(result)
# print(dir(result))
# print(result.__next__())
# print(result.__next__())
# print(result.__next__())

# print(result.__next__())
#next超出范围，就会报错

#for 语法糖
#for  先调用可迭代对象的__iter__方法，返回一个迭代器，然后再对迭代器调用__next__方法
#     直到最后一个退出

# range_iter = iter(range(10))
# print(dir(range_iter))

#懒加载 惰性求值 需要的时候再生成
# lst = [1,2,3,4,5,6,7,8]   #一次性全部生成，保存在内存中
# #range(1,9)
# for i in range(1,9):
#     print(i)


# range_iter = iter(range(10))
# from collections.abc import Iterable, Iterator
# print(isinstance(range_iter, Iterable))
# print(isinstance(range_iter, Iterator))

#实现一个迭代器
# class NumIter():
#     def __init__(self):
#         self.num = 0
#     def __iter__(self):
#         return self
#     def __next__(self):
#         self.num +=1
#         return self.num
# n1 = NumIter()
# print(dir(n1))

# for i in n1:
#     if i == 10:
#         break
#     print(i)

#生成器 不需要手动实现__iter__和__next__方法。
#是迭代器更优雅的写法
#生成器只有两个写法  一种叫做生成器表达式， 一种叫做生成器函数

#生成器表达式  -- 惰性求值
#类似于列表推导式
# result = (x for x in range(1,31) if x % 3 == 0)
# print(result)
# print(dir(result))

#生成器函数
#包含了yield关键字的函数就叫做生成器函数
# def get_content():
#     x = 2
#     yield x
#     y = 3
#     yield y
#     z = 4
#     yield z
#
# g = get_content()
# print(g)
# print(dir(g))
# print(next(g)) #第一次执行next的时候，遇到yield就退出，并且返回yield后面携带的参数，还会记录当提前执行的位置
# print(next(g)) #第二次执行的时候就会从上一次执行的地方继续执行
# # print(next(g))
# # print(next(g))

# def func1():
#     count = 1
#     while 1:
#         yield count
#         count+=1
# f = func1()
# print(next(f))
# print(next(f))

#生成器函数 实现斐波拉契数列
#1,1,2,3,5,8,13

# def func1():
#     o, t = 0, 1
#     while 1:
#         yield t
#         o, t = t, t + o
# u = func1()
# for i in range(1,10):
#     print(next(u))

#生成器的好处
#可以用更少的代码来实现迭代器的效果
#相比于容器类型更加节省内存

#大文件的处理
# def read_file(path):
#     SIZE = 65535
#     with  open(path,"rb") as f:
#         while True:
#             block = f.read(SIZE)
#             if block:
#                 yield block
#             else:
#                 return


# def counter(start_at=0):
#     count=start_at
#     while True:
#         val=(yield count)
#         print("val is :",val)
#         if val is not None:
#             count=val
#         else:
#             count+=1
# count=counter(5)
# print(type(count))
# print(count.__next__())
# print(count.__next__())
# print(count.send(99))
# print(count.__next__())
# count.close()    #关闭生成器， 关闭之后就不能再使用了
# print(count.__next__())

#yield from 后面必须返回可迭代对象

def g1():
    yield range(10)

def g2():
    yield from range(10)
    # yield from 10

    #for i in range(10):
    #     yield i

g11 = g1()
g22 = g2()

print([x for x in g11])
print([xx for xx in g22])
print([xx for xx in g22])

lst = [1,2,3]
lst_iter = iter(lst)
print(type(g11), type(lst_iter))